#include "ImageOperation.h"
#include "ImageFilter.h"

FindObject object[255];  // 물체의 정보를 기록할 배열 선언

void square(BYTE* img, int x1, int x2, int y1, int y2, int thick) {
    for (int i = 0; i < ORG_HEIGHT; i++) {
        for (int j = 0; j < ORG_WIDTH * 3; j++) {
            if ( ((j >= x1 - thick / 2 && j <= x1 + thick / 2) && (i >= y1 && i <= y2))
                    || ((j >= x2 - thick / 2 && j <= x2 + thick / 2) && (i >= y1 && i <= y2))
                    || ((i >= y1 - thick / 2 && i <= y1 + thick / 2) && (j >= x1 - 1 && j <= x2 + 1))
                    || ((i >= y2 - thick / 2 && i <= y2 + thick / 2) && (j >= x1 - 1 && j <= x2 + 1))) {  // x범위 +-1 >> 사각형 모서리 처리
                img[i * ORG_WIDTH * 3 + j * 3 + 0] = 0;
                img[i * ORG_WIDTH * 3 + j * 3 + 1] = 0;
                img[i * ORG_WIDTH * 3 + j * 3 + 2] = 255;
            }
        }
    }
}

void circle2(BYTE* img, int x, int y, int rad, int thick, int r, int g, int b) {
    int width = ORG_WIDTH;
    int height = ORG_HEIGHT;
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width * 3; j++) {
            if ((i - y) * (i - y) + (j - x) * (j - x) >= (rad - thick) * (rad - thick)
                    && (i - y) * (i - y) + (j - x) * (j - x) < (rad + thick) * (rad + thick)) {
                img[i * width * 3 + j * 3 + 0] = (BYTE) b;
                img[i * width * 3 + j * 3 + 1] = (BYTE) g;
                img[i * width * 3 + j * 3 + 2] = (BYTE) r;
            }
        }
    }
}

void cross(BYTE* img, int x, int y, int thick, int length, int r, int g, int b) {
    int width = ORG_WIDTH;
    int height = ORG_HEIGHT;
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width * 3; j++) {
            if (((j >= x - thick / 2 && j <= x + thick / 2) && (i >= y - length / 2 && i <= y + length / 2))
                    || ((j >= x - length / 2 && j <= x + length / 2) && (i > y - thick / 2 && i < y + thick / 2))) {  // X축에 등호를 사용하여 두께 보정
                img[i * width * 3 + j * 3 + 0] = (BYTE) b;
                img[i * width * 3 + j * 3 + 1] = (BYTE) g;
                img[i * width * 3 + j * 3 + 2] = (BYTE) r;
            }
        }
    }
}

void resizeImage(LPBYTE lpDest, CSize destSize, LPBYTE lpSrc, CSize srcSize, bool bSingleChannel /*= false*/) {
    ASSERT(destSize.cx != srcSize.cx);

    if (destSize.cx != srcSize.cx) {
        int nChannels = bSingleChannel ? 1 : 3;

        float scaleX = (float) srcSize.cx / (float) destSize.cx;
        float scaleY = (float) srcSize.cy / (float) destSize.cy;
        LPBYTE destPtr, srcPtr;

        for (int destY = 0; destY < destSize.cy; destY++) {
            for (int destX = 0; destX < destSize.cx; destX++) {
                int srcY = (int) (destY * scaleY);
                int srcX = (int) (destX * scaleX);
                destPtr = lpDest + ((destY * destSize.cx + destX) * nChannels);
                srcPtr = lpSrc + ((srcY * srcSize.cx + srcX) * nChannels);
                memcpy(destPtr, srcPtr, nChannels * sizeof(BYTE));
            }
        }
    }
}

void resizeImage(LPWORD lpDest, CSize destSize, LPWORD lpSrc, CSize srcSize, bool bSingleChannel /*= false*/) {
    ASSERT(destSize.cx != srcSize.cx);

    if (destSize.cx != srcSize.cx) {
        int nChannels = bSingleChannel ? 1 : 3;

        float scaleX = (float) srcSize.cx / (float) destSize.cx;
        float scaleY = (float) srcSize.cy / (float) destSize.cy;
        LPWORD destPtr, srcPtr;

        for (int destY = 0; destY < destSize.cy; destY++) {
            for (int destX = 0; destX < destSize.cx; destX++) {
                int srcY = destY * scaleY;
                int srcX = destX * scaleX;
                destPtr = lpDest + ((destY * destSize.cx + destX) * nChannels);
                srcPtr = lpSrc + ((srcY * srcSize.cx + srcX) * nChannels);
                memcpy(destPtr, srcPtr, nChannels * sizeof(WORD));
            }
        }
    }
}

void copyWithExtension(LPBYTE lpDest, LPBYTE lpSrc, int width, int height) {
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            LPBYTE ptr = lpDest + ((i * width + j) * 3);
            ptr[0] = ptr[1] = ptr[2] = lpSrc[i * width + j];
        }
    }
}

/*
 * op1 영상과 op2 영상을 AND 연산한다. (마스크 영역에 해당하는 이미지만 남기기)
 */
void andOperator(LPBYTE lpResult, LPBYTE lpOp1, LPBYTE lpOp2, int width, int height) {
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            lpResult[i * width + j] = lpOp1[i * width + j] & lpOp2[i * width + j];
        }
    }
}

void orOperator(LPBYTE lpResult, LPBYTE lpOp1, LPBYTE lpOp2, int width, int height) {
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            lpResult[i * width + j] = lpOp1[i * width + j] | lpOp2[i * width + j];
        }
    }
}

void orOperator(LPBYTE lpResult, LPBYTE lpOp1, LPBYTE lpOp2, LPBYTE lpOp3, int width, int height) {
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            lpResult[i * width + j] = lpOp1[i * width + j] | lpOp2[i * width + j] | lpOp3[i * width + j];
        }
    }
}

void subOperator(LPBYTE lpResult, LPBYTE lpOp1, LPBYTE lpOp2, int width, int height) {
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            int value = lpOp1[i * width + j] - lpOp2[i * width + j];
            lpResult[i * width + j] = MAX(0, MIN(value, 255));  // 오버, 언더플로우 방지
        }
    }
}

void subAbsOperator(LPBYTE lpResult, LPBYTE lpOp1, LPBYTE lpOp2, int width, int height) {
    for (int i = 0; i < height; i++)
        for (int j = 0; j < width; j++)
            lpResult[i * width + j] = abs(lpOp1[i * width + j] - lpOp2[i * width + j]);
}

void subAbsBinarization(LPBYTE lpResult, LPBYTE lpOp1, LPBYTE lpOp2, int width, int height, int thres) {
    for (int i = 0; i < height; i++)
        for (int j = 0; j < width; j++) {
            BYTE val = abs(lpOp1[i * width + j] - lpOp2[i * width + j]);
            if (val > thres)
                lpResult[i * width + j] = WHITE;
            else
                lpResult[i * width + j] = BLACK;
        }
}

void subAbsBinarization(LPWORD lpResult, LPWORD lpOp1, LPWORD lpOp2, int width, int height, int thres) {
    for (int i = 0; i < height; i++)
        for (int j = 0; j < width; j++) {
            WORD val = abs(lpOp1[i * width + j] - lpOp2[i * width + j]);
            if (val > thres)
                lpResult[i * width + j] = 360;
            else
                lpResult[i * width + j] = BLACK;
        }
}

void normalizeHue(LPBYTE lpDest, LPWORD lpSrc, int width, int height) {
    for (int i = 0; i < height; i++)
        for (int j = 0; j < width; j++)
            lpDest[i * width + j] = NORMALIZE_HUE(lpSrc[i * width + j]);
}

void drawRectangle(BYTE* img, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, int TH, BYTE r, BYTE g,
                   BYTE b) {
    Bresenham(img, x1, y1, x2, y2, TH, r, g, b);
    Bresenham(img, x2, y2, x3, y3, TH, r, g, b);
    Bresenham(img, x3, y3, x4, y4, TH, r, g, b);
    Bresenham(img, x4, y4, x1, y1, TH, r, g, b);
}
void drawRectangle(BYTE* img, int* x, int* y, int TH, BYTE r, BYTE g, BYTE b) {
    Bresenham(img, x[1], y[1], x[2], y[2], TH, r, g, b);
    Bresenham(img, x[2], y[2], x[3], y[3], TH, r, g, b);
    Bresenham(img, x[3], y[3], x[0], y[0], TH, r, g, b);
    Bresenham(img, x[0], y[0], x[1], y[1], TH, r, g, b);
}
void drawRectangle2(BYTE* img, int* x, int* y, int TH, BYTE r, BYTE g, BYTE b) {
    Bresenham(img, x[0], y[0], x[1], y[1], TH, 255, 255, 255);
    Bresenham(img, x[1], y[1], x[2], y[2], TH, 255, 255, 255);
    Bresenham(img, x[2], y[2], x[3], y[3], TH, 255, 255, 255);
    Bresenham(img, x[3], y[3], x[4], y[4], TH, 255, 255, 255);
    Bresenham(img, x[4], y[4], x[5], y[5], TH, 255, 255, 255);
    Bresenham(img, x[5], y[5], x[6], y[6], TH, 255, 255, 255);
    Bresenham(img, x[6], y[6], x[7], y[7], TH, 255, 255, 255);
    Bresenham(img, x[7], y[7], x[0], y[0], TH, 255, 255, 255);
}


void findVertex(BYTE* lpImg, BYTE* outImg, int x, int y, int rad, BYTE r, BYTE g, BYTE b) {
    int tmp;
    int tmpx = 0;
    int tmpy = 0;
    int count = 0;
    int i;

    int x_arr[4] = { 0, };
    int y_arr[4] = { 0, };
    int t_arr[4] = { 999, };

//int thick = 1;
    double degree = 0;

    int save[360] = { 0, };
//int savePosX[360] = { 0, };
//int savePosY[360] = { 0, };
    int printcount = 0;

    for (; rad > 0; rad = rad--) {
        for (int t = 0; t < 360; t++) {

            degree = (double) t / DEGREE;
            // tmpx, tmpy가 음수가 발생할 가능성이 있어서 메모리 오류가 났었음
            tmpx = MAX((int) (cos(degree) * rad) + x, 0);
            tmpy = MAX((int) (sin(degree) * rad) + y, 0);
            tmp = lpImg[tmpy * WRK_WIDTH + tmpx];
            lpImg[tmpy * WRK_WIDTH + tmpx] = WHITE;

            if (tmp == WHITE)
                save[t] = TRUE;
            else
                save[t] = FALSE;
        }

        printcount++;

        for (int t = 0; t < 360; t++) {
            degree = (double) t / DEGREE;

            if ((save[(t + 0) % 360] == FALSE && save[(t + 1) % 360] == FALSE && save[(t + 2) % 360] == FALSE
                    && save[(t + 3) % 360] == TRUE && save[(t + 4) % 360] == TRUE && save[(t + 5) % 360] == FALSE
                    && save[(t + 6) % 360] == FALSE && save[(t + 7) % 360] == FALSE)) {

                t_arr[count] = t;
                if (count == 1) {
                    if (t - t_arr[0] < 40)
                        break;
                }
                if (count == 2) {
                    if (t - t_arr[1] < 40)
                        break;
                }
                if (t >= 0 && t < 90) {  //x0,y0는 1사분면
                    x_arr[0] = (int) (cos(degree) * rad) + x;
                    y_arr[0] = (int) (sin(degree) * rad) + y;
                    count++;
                } else if (t >= 90 && t < 180) {
                    x_arr[1] = (int) (cos(degree) * rad) + x;
                    y_arr[1] = (int) (sin(degree) * rad) + y;
                    count++;
                } else if (t >= 180 && t < 270) {
                    x_arr[2] = (int) (cos(degree) * rad) + x;
                    y_arr[2] = (int) (sin(degree) * rad) + y;
                    count++;
                } else if (t >= 270 && t < 360) {
                    x_arr[3] = (int) (cos(degree) * rad) + x;
                    y_arr[3] = (int) (sin(degree) * rad) + y;
                    count++;
                }
                if (count == 4) {
                    drawRectangle(outImg, x_arr, y_arr, 3, r, g, b);
                    printf("4 \n");
                    return;
                } else if (count == 3) {
                    printf("3 \n");
                    if (x_arr[0] == 0) {
                        x_arr[0] = 2 * x - x_arr[2];
                        y_arr[0] = 2 * y - y_arr[2];
                    } else if (x_arr[1] == 0) {
                        x_arr[1] = 2 * x - x_arr[3];
                        y_arr[1] = 2 * y - y_arr[3];
                    } else if (x_arr[2] == 0) {
                        x_arr[2] = 2 * x - x_arr[0];
                        y_arr[2] = 2 * y - y_arr[0];
                    } else if (x_arr[3] == 0) {
                        x_arr[3] = 2 * x - x_arr[1];
                        y_arr[3] = 2 * y - y_arr[1];
                    }
                    //  x_arr[3] = 2 * x - x_arr[1];
                    //  y_arr[3] = 2 * y - y_arr[1];
                    drawRectangle(outImg, x_arr, y_arr, 3, r, g, b);
                    return;
                } else if (count == 2) {

                }
                //x_arr[count] = (int)(cos(degree)*rad) + x;
                //y_arr[count] = (int)(sin(degree)*rad) + y;
                //t = t + 30;
                printf("t : %d, count : %d x[%d] : %d, y[%d] : %d\n", t, count, count, x_arr[count], count,
                       y_arr[count]);

                //printf("x : %d, count : %d \n",t, count);
            }

        }

        for (i = 0; i < 360; i++) {
            save[i] = -1;
        }

        for (count = 0; count < 3; count++) {
            x_arr[count] = 0;
            y_arr[count] = 0;
            t_arr[count] = 999;
        }
        count = 0;
    }

    return;

}


void findVertex2(BYTE* lpImg, BYTE* outImg, int x, int y, int rad, BYTE r, BYTE g, BYTE b) {
    int i, j;
    int arr_x[8] = { 0, 0, 0, WRK_HEIGHT, WRK_HEIGHT, WRK_HEIGHT, WRK_HEIGHT, 0 };
    int arr_y[8] = { 0, 0, 0, WRK_WIDTH, WRK_WIDTH, WRK_WIDTH, WRK_WIDTH, 0 };
    double farhest;

// 1사분면 검사
    farhest = 0.0;
    for (i = MAX(y, 0); i < MIN(y + rad, WRK_HEIGHT); i++) {
        for (j = MAX(x, 0); j < MIN(x + rad, WRK_WIDTH); j++) {
            if (lpImg[i * WRK_WIDTH + j] == WHITE) {
                double dist = (SQUARE((double) (x - j)) + SQUARE((double) (y - i)));

                if (dist > farhest) {
                    farhest = dist;

                    if (i == MAX(i, arr_y[1])) {
                        arr_x[1] = j;
                        arr_y[1] = i;
                    }
                    if (j == MAX(j, arr_x[0])) {
                        arr_x[0] = j;
                        arr_y[0] = i;
                    }
                }
            }
        }
    }
// 2사분면 검사
    farhest = 0.0;
    for (i = MAX(y, 0); i < MIN(y + rad, WRK_HEIGHT); i++) {
        for (j = MAX(x - rad, 0); j < MIN(x, WRK_WIDTH); j++) {
            if (lpImg[i * WRK_WIDTH + j] == WHITE) {
                double dist = (SQUARE((double) (x - j)) + SQUARE((double) (y - i)));

                if (dist > farhest) {
                    farhest = dist;

                    if (i == MAX(i, arr_y[2])) {
                        arr_x[2] = j;
                        arr_y[2] = i;
                    }
                    if (j == MIN(j, arr_x[3])) {
                        arr_x[3] = j;
                        arr_y[3] = i;
                    }
                }
            }
        }
    }
// 3사분면 검사
    farhest = 0.0;
    for (i = MAX(y - rad, 0); i < MIN(y, WRK_HEIGHT); i++) {
        for (j = MAX(x - rad, 0); j < MIN(x, WRK_WIDTH); j++) {
            if (lpImg[i * WRK_WIDTH + j] == WHITE) {
                double dist = (SQUARE((double) (x - j)) + SQUARE((double) (y - i)));

                if (dist > farhest) {
                    farhest = dist;

                    if (j == MIN(j, arr_x[4])) {
                        arr_x[4] = j;
                        arr_y[4] = i;
                    }
                    if (i == MIN(i, arr_y[5])) {
                        arr_x[5] = j;
                        arr_y[5] = i;
                    }
                }
            }
        }
    }

// 4사분면 검사
    farhest = 0.0;
    for (i = MAX(y - rad, 0); i < MIN(y, WRK_HEIGHT); i++) {
        for (j = MAX(x, 0); j < MIN(x + rad, WRK_WIDTH); j++) {
            if (lpImg[i * WRK_WIDTH + j] == WHITE) {
                double dist = (SQUARE((double) (x - j)) + SQUARE((double) (y - i)));

                if (dist > farhest) {
                    farhest = dist;

                    if (i == MIN(i, arr_y[6])) {
                        arr_x[6] = j;
                        arr_y[6] = i;
                    }
                    if (j == MAX(j, arr_x[7])) {
                        arr_x[7] = j;
                        arr_y[7] = i;
                    }
                }
            }
        }
    }
//위치 출력
//for (i = 0; i < 8; i++)
//  printf("x[%d]:%3d y[%d]:%3d ", i, arr_x[i], i, arr_y[i]);
//printf("\n");
//for (i = 0; i < 8; i++){
//  circle(outImg, arr_x[i], arr_y[i], 2, 2, 255, 255, 255);
//}
    for (i = 0; i < 8; i++) {
        arr_x[i] *= SCALE_FACTOR;
        arr_y[i] *= SCALE_FACTOR;
    }
    drawRectangle2(outImg, arr_x, arr_y, 5, r, g, b);
}

void catImg(LPBYTE inImg, LPBYTE outImg) {
    int th = 3;
    for (int i = th; i < WRK_HEIGHT - th; i++) {
        for (int j = th; j < WRK_WIDTH - th; j++) {
            if (inImg[i * WRK_WIDTH + j] == WHITE) {
                for (int k = -th; k < th; k++) {
                    outImg[(i + k) * WRK_WIDTH + (j + k)] = 128;
                }
            }
        }
    }
}

void catColorImg(LPBYTE inImg, LPBYTE outImg, BYTE r, BYTE g, BYTE b) {
    int th = 3;

    for (int i = th; i < ORG_HEIGHT - th; i++) {
        for (int j = th; j < (ORG_WIDTH - th) * 3; j++) {
            if (inImg[i * ORG_WIDTH + j] == WHITE) {
                for (int k = -th; k < th; k++) {
                    outImg[(i + k) * ORG_WIDTH * 3 + (j + k) * 3 + 2] = r;
                    outImg[(i + k) * ORG_WIDTH * 3 + (j + k) * 3 + 1] = g;
                    outImg[(i + k) * ORG_WIDTH * 3 + (j + k) * 3 + 0] = b;
                }
            }
        }
    }
}

void Bresenham(LPBYTE img, int x1, int y1, int const x2, int const y2, int thick, BYTE r, BYTE g, BYTE b)  //line그리기 최적화 함수
               {
    int delta_x(x2 - x1);
// if x1 == x2, then it does not matter what we set here
    signed char const ix((delta_x > 0) - (delta_x < 0));
    delta_x = abs(delta_x) << 1;

    int delta_y(y2 - y1);
// if y1 == y2, then it does not matter what we set here
    signed char const iy((delta_y > 0) - (delta_y < 0));
    delta_y = abs(delta_y) << 1;

    plot(x1, y1, thick, img, r, g, b);

    if (delta_x >= delta_y) {
        // error may go below zero
        int error(delta_y - (delta_x >> 1));

        while (x1 != x2) {
            if ((error >= 0) && (error || (ix > 0))) {
                error -= delta_x;
                y1 += iy;
            }
            // else do nothing

            error += delta_y;
            x1 += ix;

            plot(x1, y1, thick, img, r, g, b);
        }
    } else {
        // error may go below zero
        int error(delta_x - (delta_y >> 1));

        while (y1 != y2) {
            if ((error >= 0) && (error || (iy > 0))) {
                error -= delta_y;
                x1 += ix;
            }
            // else do nothing

            error += delta_x;
            y1 += iy;

            plot(x1, y1, thick, img, r, g, b);
        }
    }
}

void plot(int x, int y, int thick, LPBYTE img, BYTE r, BYTE g, BYTE b) {  // 점을 찍는 함수
    for (int i = -thick; i < thick; i++) {
        int temp = (y + i) * ORG_WIDTH * 3 + (x + i) * 3;
        if (temp > 0 && temp < ORG_WIDTH * ORG_HEIGHT * 3) {
            img[temp + 0] = r;
            img[temp + 1] = g;
            img[temp + 2] = b;
        }
    }
}

int callLabel(int initx, int inity, int iHeight, int iWidth, LPBYTE pImg) {
    int i, j;
    BYTE labelNum = 1;

    /* 노이즈 제거를 거친 후 진행하기 때문에
     영상의 끝 픽셀은 WHITE이므로 검사하지 않는다. */
    for (i = inity + 1; i < iHeight - 1; i++) {
        for (j = initx + 1; j < iWidth - 1; j++) {
            if (pImg[i * WRK_WIDTH + j] == WHITE) {
                pImg[i * WRK_WIDTH + j] = labelNum;
                /* 번호 매기는 함수 호출 */
                labeling(initx, inity, iHeight, iWidth, &labelNum, pImg);
                /* 라벨번호 증가 */
                labelNum++;
            }
        }
    }

    return labelNum;
}

/* 특정영역에 대해 번호를 매기는 함수 */
void labeling(int initx, int inity, int iHeight, int iWidth, LPBYTE labelNum, LPBYTE pImg) {
    int i, j;
    int rwsize = WRK_WIDTH;
    int labelState = 1;     // 라벨링이 되고 있는지의 정보를 확인

    /* 물체의 정보 초기화 */
    BYTE labelNumber = *labelNum;
    object[labelNumber].areaSize = 1;
    object[labelNumber].leftX = iWidth;
    object[labelNumber].rightX = 0;
    object[labelNumber].bottomY = iHeight;
    object[labelNumber].topY = 0;

    while (labelState) {
        labelState = 0;

        for (i = inity + 1; i < iHeight - 1; i++) {
            for (j = initx + 1; j < iWidth - 1; j++) {
                if (pImg[i * rwsize + j] == labelNumber) {
                    /* 기준점에 대해 아래쪽 검사 */
                    if (pImg[(i - 1) * rwsize + (j)] == WHITE) {
                        pImg[(i - 1) * rwsize + (j)] = labelNumber;

                        /* 특정영역의 상, 하, 좌, 우 값을 설정 */
                        if (object[labelNumber].bottomY > (i - 1))
                            object[labelNumber].bottomY = i - 1;
                        if (object[labelNumber].topY < (i - 1))
                            object[labelNumber].topY = i - 1;
                        if (object[labelNumber].leftX > (j))
                            object[labelNumber].leftX = j;
                        if (object[labelNumber].rightX < (j))
                            object[labelNumber].rightX = j;

                        /* 물체의 사이즈를 측정 */
                        object[labelNumber].areaSize++;
                        /* 라벨링 하는 중이라고 알린다. */
                        labelState = 1;
                    }

                    /* 기준점에 대해 위쪽 검사 */
                    if (pImg[(i + 1) * rwsize + (j)] == WHITE) {
                        pImg[(i + 1) * rwsize + (j)] = labelNumber;

                        /* 특정영역의 상, 하, 좌, 우 값을 설정 */
                        if (object[labelNumber].bottomY > (i + 1))
                            object[labelNumber].bottomY = i + 1;
                        if (object[labelNumber].topY < (i + 1))
                            object[labelNumber].topY = i + 1;
                        if (object[labelNumber].leftX > (j))
                            object[labelNumber].leftX = j;
                        if (object[labelNumber].rightX < (j))
                            object[labelNumber].rightX = j;

                        /* 물체의 사이즈를 측정 */
                        object[labelNumber].areaSize++;
                        /* 라벨링 하는 중이라고 알린다. */
                        labelState = 1;
                    }

                    /* 기준점에 대해 왼쪽 검사 */
                    if (pImg[(i) * rwsize + (j - 1)] == WHITE) {
                        pImg[(i) * rwsize + (j - 1)] = labelNumber;

                        /* 특정영역의 상, 하, 좌, 우 값을 설정 */
                        if (object[labelNumber].bottomY > (i))
                            object[labelNumber].bottomY = i;
                        if (object[labelNumber].topY < (i))
                            object[labelNumber].topY = i;
                        if (object[labelNumber].leftX > (j - 1))
                            object[labelNumber].leftX = j - 1;
                        if (object[labelNumber].rightX < (j - 1))
                            object[labelNumber].rightX = j - 1;

                        /* 물체의 사이즈를 측정 */
                        object[labelNumber].areaSize++;
                        /* 라벨링 하는 중이라고 알린다. */
                        labelState = 1;
                    }

                    /* 기준점에 대해 오른쪽 검사 */
                    if (pImg[(i) * rwsize + (j + 1)] == WHITE) {
                        pImg[(i) * rwsize + (j + 1)] = labelNumber;

                        /* 특정영역의 상, 하, 좌, 우 값을 설정 */
                        if (object[labelNumber].bottomY > (i))
                            object[labelNumber].bottomY = i;
                        if (object[labelNumber].topY < (i))
                            object[labelNumber].topY = i;
                        if (object[labelNumber].leftX > (j + 1))
                            object[labelNumber].leftX = j + 1;
                        if (object[labelNumber].rightX < (j - 1))
                            object[labelNumber].rightX = j - 1;

                        /* 물체의 사이즈를 측정 */
                        object[labelNumber].areaSize++;
                        /* 라벨링 하는 중이라고 알린다. */
                        labelState = 1;
                    }
                }
            }
        }
    }

    return;
}

void processing(LPBYTE himg, LPBYTE edgeImg, LPBYTE output, Color color) {
    int r = color.Red;
    int g = color.Green;
    int b = color.Blue;
//filterMin(himg, himg, WRK_WIDTH, WRK_HEIGHT);
    mopOpening(himg, himg, WRK_WIDTH, WRK_HEIGHT, 2, 2);
    catImg(edgeImg, himg);
    filterMax(himg, himg, WRK_WIDTH, WRK_HEIGHT);
    filterMax(himg, himg, WRK_WIDTH, WRK_HEIGHT);
    CSize originalSize = { ORG_WIDTH, ORG_HEIGHT };
    CSize workingSize = { WRK_WIDTH, WRK_HEIGHT };
    BYTE buf[ORG_WIDTH * ORG_HEIGHT];
    resizeImage(buf, originalSize, himg, workingSize, true);
//catColorImg(buf, output, r, g, b);
}

void binarization(LPBYTE lpDest, LPBYTE lpSrc, int width, int height, int threshold) {
    LPBYTE lpTmp = lpDest;
    if (lpDest == lpSrc)
        lpTmp = new BYTE[width * height];

    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            int idx = i * width + j;
            if (threshold <= lpSrc[idx])
                lpTmp[idx] = WHITE;
            else
                lpTmp[idx] = BLACK;
        }
    }

    if (lpDest == lpSrc) {
        memcpy(lpDest, lpTmp, width * height * sizeof(lpTmp[0]));
        delete[] lpTmp;
    }
}

void trinarization(LPBYTE lpDest, LPBYTE lpSrc, int width, int height, int thMin, int thMax) {
    LPBYTE lpTmp = lpDest;
    if (lpDest == lpSrc)
        lpTmp = new BYTE[width * height];

    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            int idx = i * width + j;
            if (thMin <= lpSrc[idx] && lpSrc[idx] <= thMax)
                lpTmp[idx] = WHITE;
            else
                lpTmp[idx] = BLACK;
        }
    }

    if (lpDest == lpSrc) {
        memcpy(lpDest, lpTmp, width * height * sizeof(lpTmp[0]));
        delete[] lpTmp;
    }
}

void trinarization(LPWORD lpDest, LPWORD lpSrc, int width, int height, int thMin, int thMax) {
    LPWORD lpTmp = lpDest;
    if (lpDest == lpSrc)
        lpTmp = new WORD[width * height];

    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            int idx = i * width + j;
            if (thMin <= lpSrc[idx] && lpSrc[idx] <= thMax)
                lpTmp[idx] = WHITE;
            else
                lpTmp[idx] = BLACK;
        }
    }

    if (lpDest == lpSrc) {
        memcpy(lpDest, lpTmp, width * height * sizeof(lpTmp[0]));
        delete[] lpTmp;
    }
}
